package com.itlong.cloud.property.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.itlong.cloud.POJO.DTO.property.PropertyAddVisitorDTO;
import com.itlong.cloud.POJO.DTO.sdk.VisitorServerGetListDTO;
import com.itlong.cloud.POJO.DTO.sdk.VisitorServerSubmitDTO;
import com.itlong.cloud.POJO.PO.AppVisitorPassCodeRecordPO;
import com.itlong.cloud.POJO.PO.DeviceBusinessChangeLogPO;
import com.itlong.cloud.POJO.PO.DeviceBusinessElevatorChangeLogPO;
import com.itlong.cloud.POJO.PO.DeviceBusinessEntranceChangeLogPO;
import com.itlong.cloud.POJO.VO.sdk.VisitorServerGetListVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IPropertyVisitorPassCodeRecordDao;
import com.itlong.cloud.property.dao.IVisitorServerDao;
import com.itlong.cloud.property.service.IVisitorServerService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.picture.QrcodeUtils;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.random.RandomUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.NoSuchProviderException;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * <desc>
 *      访客机API
 * </desc>
 *
 * @create 2019/04/29
 */
@Service
@RefreshScope
public class VisitorServerServiceImpl implements IVisitorServerService{
    private static final Logger LOG = LoggerFactory.getLogger(VisitorServerServiceImpl.class);

    @Autowired
    IVisitorServerDao iVisitorServerDao;

    @Autowired
    IPropertyVisitorPassCodeRecordDao iPropertyVisitorPassCodeRecordDao;

    @Autowired
    private MessageSender messageSender;


    @Autowired
    private RedisService redisService;
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock writeLock;
    @PostConstruct
    public void init(){
        writeLock = lock.writeLock();
    }

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;
    /**
     * <desc>
     *      验证身份信息
     * </desc>
     *
     * @param appid
     * @param appSecret
     * @return
     * @author Jiaqi.X
     * @createDate 2019/04/29
     */
    @Override
    public Integer checkIdentity(String projectId,String appid, String appSecret) {
        return iVisitorServerDao.checkIdentity(projectId,appid,appSecret);
    }

    /**
     * <desc>
     *      获取地址信息
     * </desc>
     *
     * @param projectId
     * @param buildId
     * @param unitId
     * @return
     * @author Jiaqi.X
     * @createDate 2019/04/29
     */
    @Override
    public List<Map<String, Object>> getAddressInfo(String projectId, String buildId, String unitId) {
        if(StringUtils.isNotBlank(projectId) && StringUtils.isNotBlank(buildId)){
            //返回单元信息
            return iVisitorServerDao.getUnits(projectId,buildId);
        }else if(StringUtils.isNotBlank(projectId) && StringUtils.isNotBlank(unitId)){
            //返回房间信息
            return iVisitorServerDao.getRooms(projectId,unitId);
        }else if(StringUtils.isNotBlank(projectId)){
            //返回楼栋信息
            return iVisitorServerDao.getBuilds(projectId);
        }else{
            return null;
        }
    }

    /**
     * <desc>
     *      提交访客单
     * </desc>
     *
     * @param dto
     * @return
     * @author Jiaqi.X
     * @createDate 2019/04/29
     */
    @Override
    public  Map<String,Object> submit(VisitorServerSubmitDTO dto) throws Exception {
        //如果次数为空或者大于10 默认为10
        if(StringUtils.isBlank(dto.getCountLimit())){
            dto.setCountLimit("1000");
        }
        Map<String,Object> qrcodeConfigure = iPropertyVisitorPassCodeRecordDao.getVisitorConfigure(dto.getProjectId());
        String visitorQrCodeTimesRestrict = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("visitorQrCodeTimesRestrict"));
        String visitorQrCodeUsableTimes = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("visitorQrCodeUsableTimes"));
        if("1".equals(visitorQrCodeTimesRestrict)){
            dto.setCountLimit(visitorQrCodeUsableTimes);
        }
        AppVisitorPassCodeRecordPO passPO=new AppVisitorPassCodeRecordPO();
        passPO.setIntervieweeName(dto.getVisitName());
        passPO.setBuildId(dto.getBuildId());
        passPO.setUnitId(dto.getUnitId());
        passPO.setRoomId(dto.getRoomId());
        passPO.setCreateTime(new Date());
        passPO.setSource(5);
        passPO.setIdcardKey(dto.getVisitorIdCardKey());
        //如果有效时间为空，默认为当前创建时间
        if(StringUtils.isBlank(dto.getEffectiveTime())){
            dto.setEffectiveTime("1440");
        }
        passPO.setStartTime(DateUtil.formatStringToDate(dto.getVisitorTime(),DateUtil.DATE_FORMAT_TYPE1));
        passPO.setPassId(LogicIdUtil.bussinessId());
        passPO.setVisitorName(dto.getVisitorName());
        passPO.setVisitorPhone(dto.getVisitorPhone());
        passPO.setStatus(DataStatusEnum.NORMAL.getType());
        String roomNum = iPropertyVisitorPassCodeRecordDao.getRoomNumByRoomId(dto.getRoomId());
        if(StringUtils.isNotBlank(roomNum)){
            passPO.setFloorNum(roomNum.substring(0, 2));
        }
        if(StringUtils.isBlank(roomNum)){
            Map<String,Object> errMap = new HashMap<>();
            errMap.put("errMsg","1");
            return errMap;
        }
        PropertyAddVisitorDTO addressDTO = new PropertyAddVisitorDTO();
        addressDTO.setProjectId(dto.getProjectId());
        addressDTO.setBuildId(dto.getBuildId());
        addressDTO.setUnitId(dto.getUnitId());
        addressDTO.setRoomId(dto.getRoomId());
        //云对讲机号 多个，号分隔
        Map<String,Object> cloudTalkMap=iPropertyVisitorPassCodeRecordDao.getCloudIntercomUniquesByBuildIdAndUnitId(addressDTO);
        String cloudUniques = cloudTalkMap!=null?cloudTalkMap.get("deviceIds").toString():null;
        //门禁机号 多个，号分隔
        Map<String,Object> entranceMap=iPropertyVisitorPassCodeRecordDao.getEntranceUniquesByBuildIdAndUnitId(addressDTO);
        String entranceUniques = entranceMap!=null?entranceMap.get("deviceIds").toString():null;
        //电梯机号 多个，号分隔
        String elevatorUniques=iPropertyVisitorPassCodeRecordDao.getElevatorUniquesByBuildIdAndUnitId(addressDTO);
        //获取房间号的楼栋信息
        //如果没有设备权限直接返回null
        if(StringUtils.isNotBlank(cloudUniques) || StringUtils.isNotBlank(entranceUniques) || StringUtils.isNotBlank(elevatorUniques)) {
            String uniques = StringUtils.isNotBlank(cloudUniques) ? cloudUniques + "," : "";
            uniques += StringUtils.isNotBlank(entranceUniques) ? uniques + entranceUniques  : uniques;
            //为了防止门禁与云对讲机号重复，现对设备机号进行去重处理
            String[] allDeviceIds = StringHandlerUtil.splitString(uniques);
            Set<String> setDeviceIds = new HashSet<>();
            String deviceIds = "";
            for (String deviceId : allDeviceIds) {
                if (!deviceId.equals("null") && setDeviceIds.add(deviceId)) {
                    deviceIds += StringHandlerUtil.autlSupply(4,deviceId,"0") + ",";
                }
            }
            //设置门禁的id
            passPO.setDeviceId(StringUtils.isNotBlank(deviceIds) ? deviceIds.substring(0, deviceIds.length() - 1) : "");
            passPO.setUseNum(0);
            //生成二维码信息
            Map<String,Object> codeResult;
            codeResult = this.getQrCode(elevatorUniques, deviceIds, dto.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                    "visitorServer",dto.getVisitorPhone(),Integer.valueOf(dto.getEffectiveTime()),
                    roomNum.substring(0,2));
            passPO.setQrcode(codeResult.get("qrcode").toString().toUpperCase());
            passPO.setVisitorUuid(codeResult.get("visitorUuid").toString());
        }else{
            passPO.setQrcode("00000000000000000000000000000000000000000000000000");
        }
        //生成二维码图片
        BufferedImage bim = QrcodeUtils.getQR_CODEBufferedImage(passPO.getQrcode(), BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(bim, "png", out);
        InputStream input = new ByteArrayInputStream(out.toByteArray());
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                input,
                "png",
                FILE_ACCESS_URL,
                FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
        );
        Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
        Boolean returnCode = (Boolean)resultMap.get("returnCode");
        if (returnCode == true){
            passPO.setQrcodeUrl(resultMap.get("accessPath").toString());
        }
        passPO.setProjectId(dto.getProjectId());
        //设置有效结束时间
        passPO.setEndTime(DateUtil.addCurrentTime(passPO.getStartTime(),
                Integer.valueOf(dto.getEffectiveTime()) * 60 * 1000));
        passPO.setNum(Integer.valueOf(dto.getCountLimit()));
        passPO.setSource(VisitorSourceTypeEnum.PROPERTY.getType());
        //判断项目配置信息 生成动态密码 0在线版 1离线版
        Integer otpOnline = iPropertyVisitorPassCodeRecordDao.getOtpOnlineByProjectId(dto.getProjectId());
        if(otpOnline == 0) {
            //在线版验证方式
            String random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
            int repeat = 1;
            try {
                //获取写锁
                writeLock.lock();
                while (repeat > 0) {
                    //检查是否重复
                    repeat = iPropertyVisitorPassCodeRecordDao.checkRepeatPassword(random,
                            DateUtil.fomatDate(passPO.getStartTime(), DateUtil.YYYYMMDDHHMM),
                            DateUtil.fomatDate(passPO.getEndTime(), DateUtil.YYYYMMDDHHMM));
                    if (repeat > 0) {
                        random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
                    }
                }
                passPO.setPassword(random);
            } catch (Exception e) {
                throw e;
            } finally {
                writeLock.unlock();
            }
            passPO.setType(DynamicPasswordTypeEnum.ONLINE.getType());
        }else{
            //脱机版验证方式
            //获取加密后的项目秘钥
            String encriptProjKey=StringHandlerUtil.bytesToHexStr(DesEncryptUtil.getQrcodeKey(DesEncryptUtil.QRCODE_INIT_KEY, dto.getProjectId()));
            //动态密码规则 楼层（03）+权限组号（01）+四位密码
            StringBuilder password = new StringBuilder(StringHandlerUtil.autlSupply(2,((Integer)Math.abs(Integer.valueOf(passPO.getFloorNum()))).toString(),"0"));
            //获取权限组号
            String unitGroupNum = iPropertyVisitorPassCodeRecordDao.getGroupNumByUnitId(dto.getUnitId());
            if(StringUtils.isNotBlank(unitGroupNum) && Integer.valueOf(unitGroupNum) <= 99){
                password.append(unitGroupNum);
            }else{
                password.append("00");
            }
            StringBuilder encriptValue = new StringBuilder(password.toString());
            encriptValue.append(DateUtil.fomatDate(passPO.getEndTime(),"yyMMdd"));
            //获取时间段
            List<String> times = DateUtil.getIntervalTimeList("00:00:00","23:59:59",30);
            for(Integer i = 0 ; i<times.size() ; i++){
                if(i == times.size() -1 ){
                    encriptValue.append("48");
                    break;
                }else if(DateUtil.formatStringToDate(times.get(i),"HH:mm:ss").getTime() <=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime()
                        && DateUtil.formatStringToDate(times.get(i+1),"HH:mm:ss").getTime() >=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime() ){
                    encriptValue.append(StringHandlerUtil.autlSupply(2,((Integer)(i+1)).toString(),"0"));
                    break;
                }
            }
            //备用字节
            encriptValue.append("0000");
            String des = DesEncryptUtil.getUserKey(encriptValue.toString(),encriptProjKey);
            String hex = des.substring(des.length()-6,des.length());
            hex=((Integer)Integer.parseInt(hex,16)).toString();
            password.append(hex.substring(hex.length()-4,hex.length()));
            passPO.setPassword(password.toString());
            passPO.setType(DynamicPasswordTypeEnum.OFFLINE.getType());
        }
        passPO.setCheckOperator("系统");
        passPO.setCheckStatus(1);
        passPO.setOwnerCheckStatus(1);
        passPO.setCheckTime(new Date());
        passPO.setOwnerCheckTime(new Date());
        passPO.setPassNumber(RandomUtil.getRandomStringBySix(6));
        iPropertyVisitorPassCodeRecordDao.save(SqlUtil.durableData(passPO, PlatformConstants.TABLE_SAVE));
        //如果申请的访客有身份证序号,没有人脸信息,则发送云电梯,云门禁指令
        if (dto.getVisitorIdCardKey() != null) {
            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
            JSONObject json = new JSONObject();
            json.put("userId", passPO.getPassId());
            json.put("projectId", dto.getProjectId());
            DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT, json,dto.getProjectId());
            changeLogPOS.add(deviceBusinessChangeLogPO);
            JSONObject dataJs = new JSONObject();
            dataJs.put("data",changeLogPOS);
            //云电梯
            DeviceBusinessElevatorChangeLogPO deviceBusinessElevatorChangeLogPO
                    = new DeviceBusinessElevatorChangeLogPO(dto.getProjectId(),
                    CloudElevatorChangeBusinessEnum.PUSH_USER_PROJECT,json.toJSONString());
            List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
            deviceElevatorChangeLogPOS.add(deviceBusinessElevatorChangeLogPO);
            dataJs.put("data",deviceElevatorChangeLogPOS);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);

            // 云门禁
            List<DeviceBusinessEntranceChangeLogPO> changeEntranceLogPOS = new ArrayList<>();
            changeEntranceLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_USER_PROJECT, json, dto.getProjectId()));
            dataJs.put("data", changeEntranceLogPOS);
            //发送云门禁指令
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );
            //云对讲
            List<DeviceBusinessChangeLogPO> changeCloudTalkLogPOS = new ArrayList<>();
            JSONObject cloudTalkJson = new JSONObject();
            cloudTalkJson.put("userId", passPO.getPassId());//访客推送的时候使用V- + 访客记录编号  来区分业主还是访客
            cloudTalkJson.put("projectId", dto.getProjectId());
            DeviceBusinessChangeLogPO deviceCloudTalkChangeLogPO =
                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT, cloudTalkJson,dto.getProjectId());
            changeCloudTalkLogPOS.add(deviceCloudTalkChangeLogPO);
            JSONObject cloudTalkJs = new JSONObject();
            cloudTalkJs.put("data",changeCloudTalkLogPOS);
            messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                    JsonUtil.toJSON(cloudTalkJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
        }
        resultMap.put("passId",passPO.getPassId());
        return resultMap;
    }

    /**
     * <desc>
     *      查询访客单列表
     * </desc>
     *
     * @param dto
     * @return
     * @author Jiaqi.X
     * @createDate 2019/04/29
     */
    @Override
    public Page<VisitorServerGetListVO> getList(VisitorServerGetListDTO dto) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(dto);
        //分页类默认pageSize为20
        Page<VisitorServerGetListVO> page = new Page<>();
        page.getPage().setPageSize(dto.getPageSize());
        page.getPage().setCurrentPage(dto.getCurrentPage());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        //填充返回数据集
        page.setRows(iVisitorServerDao.getPage(params), iVisitorServerDao.getPageCount(params));
        List<VisitorServerGetListVO> list = page.getRows();
        Date date = new Date();
        for(VisitorServerGetListVO vo : list){
            //判断是否过期
            if(DateUtil.formatStringToDate(vo.getEndTime(), DateUtil.DATE_FORMAT_TYPE1).getTime() < date.getTime()){
                vo.setOverdue(1);
            }else{
                vo.setOverdue(0);
            }
            //查询地址
            vo.setVisitAddress(iVisitorServerDao.getVisitAddress(vo.getRoomId()));
        }
        page.setRows(list);
        return page;
    }

    /**
     * <desc>
     *      审批
     * </desc>
     *
     * @param projectId
     * @param visitorNo
     * @return
     * @author Jiaqi.X
     * @createDate 2019/04/29
     */
    @Override
    public String approve(String projectId, String visitorNo) throws Exception {
        //根据访客单查询访客id
        String passId = iVisitorServerDao.getPassIdByVisitorNo(visitorNo);
        this.sendMessage(passId,projectId);
        iPropertyVisitorPassCodeRecordDao.propertyCheckVisitor(passId,1,"访客机");
        return passId;
    }

    /**
     * <desc>
     *      向设备推送访客人脸信息
     * </desc>
     * @param passId 访客单ID
     * @param projectId 项目编号
     * @return
     * @author JuGuang.S
     * @createDate 2019/05/21
     */
    public void sendMessage(String passId,String projectId) throws Exception{
        List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
        JSONObject json = new JSONObject();
        json.put("userId", passId);//访客推送的时候使用V- + 访客记录编号  来区分业主还是访客
        json.put("projectId", projectId);
        DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT, json,projectId);
        changeLogPOS.add(deviceBusinessChangeLogPO);
        JSONObject dataJs = new JSONObject();
        dataJs.put("data",changeLogPOS);
        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
    }

    /**
     * <desc>
     *      生成访客通行二维码
     * </desc>
     *
     * @param doorIds 门禁id（机号） 多个,号分隔
     * @param projectId 项目id
     * @param userId 用户id
     * @param phoneNum 当前用户手机号
     * @return
     */
    private Map<String,Object> getQrCode(String elevatorUniques,String doorIds,String projectId,
                                         String startTime,String userId,String phoneNum,Integer timeLimit,String floorNum) throws NoSuchProviderException, ParseException {
        Map<String,Object> result = new HashMap<>();
        //开始拼接二维码
        StringBuffer qrcode=new StringBuffer("");
        //协议版本 1Byte, Hex码 偶数代表业主，奇数代表访客
        qrcode.append(AppQrcodeProtocolVersionEnum.FOURTH.getType());
        //用户类型 1Byte，Hex码。 暂定0x11表示物业管理员；
        qrcode.append(AppQrcodeUserTypeEnum.OWNER.getType());
        //用户UID 目前生成规则为用户手机号 不足6btye末尾补0
//        qrcode.append(StringHandlerUtil.autlSupplyLast(12,phoneNum,"0"));
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR, 10);
        String random = ((Long)calendar.getTime().getTime()).toString();
        String visitorUuid = random.substring(random.length() - 12 ,random.length());
        qrcode.append(visitorUuid);
        //生成日期 格式 yyMMddHHmm
        //生成日期 格式 yyMMddHHmm 由于设备时间与后台实际存在相差几分钟的情况，故生成二维码的有效开始时间提前十分钟
        Calendar beforeTime = Calendar.getInstance();
        beforeTime.setTime(DateUtil.formatStringToDate(startTime,DateUtil.YYYYMMDDHHMM));
        beforeTime.add(Calendar.MINUTE, -10);// 10分钟之前的时间
        Date beforeD = beforeTime.getTime();
        qrcode.append(DateUtil.fomatDate(DateUtil.formatStringToDate(startTime,DateUtil.YYYYMMDDHHMM),DateUtil.YYMMDDHHMM));
        //流水号：1Byte，Hex码
//        String cacheKey= RedisConstant.REDIS_APP_VISITOR_QRCODE_SERIAL_NUMBER_CACHE+userId+ DateUtil.fomatDate(new Date(), DateUtil.YYMMDD);
//        Integer serialNumber=(Integer)redisService.getObject(cacheKey, Integer.class);
//        if(serialNumber!=null){
//            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
//        }else{
//            serialNumber=1;
//            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
//        }
//        redisService.set(cacheKey, RedisConstant.REDIS_APP_VISITOR_QRCODE_SERIAL_NUMBER_CACHE_TIME, Integer.valueOf(serialNumber)+1);
        qrcode.append("34");
        //有效时间 hex 码
        if(timeLimit==null) {
            qrcode.append("90");
        }else{
            qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(timeLimit / 10),"0").toUpperCase());
        }
        Map<String,Object> qrcodeConfigure = iPropertyVisitorPassCodeRecordDao.getVisitorConfigure(projectId);
        String visitorQrCodeTimesRestrict = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("visitorQrCodeTimesRestrict"));
        String chargeMode = StringHandlerUtil.getNullOrStringForObject(qrcodeConfigure.get("chargeMode"));
        //有效次数 hex码
        if("1".equals(visitorQrCodeTimesRestrict) || "2".equals(chargeMode)){
            qrcode.append("01");
        }else{
            qrcode.append("00");
        }
        String identifier="";
        //电梯门禁标识 如有电梯和门禁权限时为0x03；只有电梯而无门禁权限时为0x01；只有门禁权限时为0x02
        if(StringUtils.isNotBlank(doorIds) && StringUtils.isNotBlank(elevatorUniques)){
            qrcode.append("03");
            identifier="03";
        }else if(StringUtils.isNotBlank(doorIds)){
            qrcode.append("02");
            identifier="02";
        }else if(StringUtils.isNotBlank(elevatorUniques)){
            qrcode.append("01");
            identifier="01";
        }else{
            qrcode.append("00");
            identifier="00";
        }
        if(!identifier.equals("00")) {
            //转换得到电梯及门禁数组
            String doors[] = StringHandlerUtil.splitString(doorIds);
            String floors[] = StringHandlerUtil.splitString(elevatorUniques);
            //门禁
            if(!identifier.equals("01")) {
                //门禁数量 HEX码
                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(doors.length).toUpperCase(), "0"));
                //门禁机号 HEX码
                qrcode.append(StringHandlerUtil.assembleDeviceNum(doors));
            }
            //电梯
            if(!identifier.equals("02")) {
                Map<String,Set<String>> builds = new HashMap<>();
                //对电梯按照楼层权限权限分组
                for(String f : floors){
                    //电梯权限 HEX码
                    String floorNo = iPropertyVisitorPassCodeRecordDao.getFloorAuthByFloorNumAndDeviceUnique(floorNum, projectId + "1" + StringHandlerUtil.autlSupply(4,f,"0"));
                    if(StringUtils.isNotEmpty(floorNo)) {
                        boolean add = false;
                        for (String k : builds.keySet()) {
                            if (k.equals(floorNo)) {
                                Set<String> deviceUniques = builds.get(k);
                                deviceUniques.add(f);
                                add = true;
                            }
                        }
                        if (!add) {
                            Set<String> deviceUniques = new HashSet<>();
                            deviceUniques.add(f);
                            builds.put(floorNo, deviceUniques);
                        }
                    }
                }
                //有权限的电梯楼栋单元数量 最多8个单元 超过8个单元按拥有所有电梯权限处理
                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(builds.keySet().size()).toUpperCase(), "0"));
                for(String floor : builds.keySet()){
                    //所属单元电梯数量 HEX 码
                    qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(builds.get(floor).size()).toUpperCase(), "0"));
                    //所属单元电梯机号 HEX码
                    qrcode.append(StringHandlerUtil.assembleDeviceNum(builds.get(floor).toArray(new String[builds.get(floor).size()])));
                    result.put("floorNo",floorNum);
                    //设置有权限的楼层数量
                    qrcode.append("01");
                    //设置楼层号和直达楼层
                    qrcode.append(StringUtils.isBlank(floor) ? "00" : StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floor)).toUpperCase(), "0"));
                    qrcode.append(StringUtils.isBlank(floor) ? "00" : StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floor)).toUpperCase(), "0"));
                }
            }
        }
        String value=qrcode.substring(16,32);
        //获取项目秘钥
        String projectKey=iPropertyVisitorPassCodeRecordDao.getQrcodeProjectKey(projectId);
//        LOG.info(String.format("【访客二维码数据监控】：projectId:%s,value:%s,projectKey:%s,qrcode:%s,mac:%s",projectId,value,projectKey,qrcode.toString()
//                , DesEncryptUtil.ownerAndVisitorMacEncrypt(value, projectKey, qrcode.toString())));
        qrcode.append(DesEncryptUtil.ownerAndVisitorMacEncrypt(value, projectKey, qrcode.toString()));
        result.put("qrcode",qrcode);
        result.put("visitorUuid",visitorUuid);
        return result;
    }


}
